home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1999 #2
/
Amiga Plus CD - 1999 - No. 2.iso
/
System-Boost
/
Workbench
/
Archive
/
XPK
/
xpk_Source
/
shell
/
xBench.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-11-15
|
13KB
|
560 lines
#define NAME "xBench"
#define DISTRIBUTION "(Freeware) "
#define VERSION "2"
#define REVISION "9"
/* Programmheader
Name: xBench
Author: SDI (before 1.1 Urban Dominik Müller)
Distribution: PD
Description: xpk benchmark utility
Compileropts: -gM
Linkeropts: -l xpkmaster amiga -gsi
1.1 29.11.96 : added version string
1.2 20.12.96 : added output telling the caller mechanism
2.0 31.03.97 : now OS 2.0 and up only, rewritten, now an utility to
allow users making benchmarks
2.1 01.04.97 : fixed some errors
2.2 23.04.97 : fixed time calculation
2.3 10.05.97 : added ALL flag, use with care!
2.4 08.06.97 : added forgotten TAG_DONE
2.5 20.06.97 : added Pattern Matching
2.6 10.10.97 : changed output style to prevent errors on large files
2.7 24.03.98 : added third buffer for source buffer check
2.8 19.07.98 : moved uncrunched length to top line for better output
2.9 24.08.98 : added logfile support
*/
#include <proto/dos.h>
#include <proto/timer.h>
#include <proto/xpkmaster.h>
#include <proto/exec.h>
#include <exec/memory.h>
#include <exec/devices.h>
#include "SDI_defines.h"
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
/* METHOD's are:
<mode - upper case, 4 chars>[.<mode - dec number>]
*/
#define PARAMS "FILENAME/A,PASSWORD/K,METHOD/M,TEST/S,ALL/S,SAVE/K," \
"LOG=LOGFILE/K"
#define HEADER "File '%s' with a size of %ld bytes.\n" \
"Type Num Version P CSize CTime CSpd UTime USpd Rate\n"
#define DATATXT "%s: %3ld %2ld.%ld%s %s %8ld %6ld.%02ld %9ld %6ld.%02ld %9ld %3ld.%ld\n"
#define SIZEERR "%s: FileSize false after decrunching %ld != %ld\n"
#define BUFERR "%s: Decrunched buffer different to source!\n"
#define SRCERR "%s: Source buffer destroyed!\n"
struct Args {
STRPTR filename;
STRPTR password;
STRPTR * method;
ULONG test;
ULONG all;
STRPTR save;
STRPTR logfile;
};
struct TestData {
STRPTR sbuf;
STRPTR cbuf;
ULONG sbufsize;
STRPTR pbuf;
ULONG pbufsize;
STRPTR ubuf;
ULONG ubufsize;
STRPTR password;
ULONG test;
ULONG all;
BPTR logfh;
STRPTR save;
struct FileInfoBlock *fib;
struct XpkPackerInfo *pinfo;
struct XpkMode *minfo;
};
struct BenchData {
STRPTR method;
ULONG mode;
ULONG version;
ULONG revision;
STRPTR pad;
STRPTR password;
ULONG CSize;
ULONG CTime;
ULONG CTime100;
ULONG CSpd;
ULONG UTime;
ULONG UTime100;
ULONG USpd;
ULONG Rate;
ULONG Rate10;
};
struct DosLibrary * DOSBase;
struct ExecBase * SysBase;
struct Library * XpkBase;
struct Device * TimerBase;
ULONG DoIt(STRPTR name, struct TestData *tdat, STRPTR *method);
LONG GetPackData(struct BenchData *b, struct TestData *t, STRPTR pwd);
void DoTest(struct TestData *data, STRPTR method, ULONG mode);
void ScanMethods(struct TestData *data, STRPTR method);
void PrintTxt(BPTR logfh, STRPTR txt, ...);
void VPrintTxt(BPTR logfh, STRPTR txt, APTR args);
void PrintErr(BPTR logfh, ULONG err, STRPTR method);
void ScanPackers(struct TestData *data);
#define PATHNAME_SIZE 256
ULONG start(void) /* not named main, to get error with startup code ! */
{
ULONG error = RETURN_FAIL;
struct DosLibrary * dosbase;
struct Process * task;
SysBase = (*((struct ExecBase **) 4));
/* test for WB and reply startup-message */
if(!(task = (struct Process *) FindTask(0))->pr_CLI)
{
WaitPort(&task->pr_MsgPort);
Forbid();
ReplyMsg(GetMsg(&task->pr_MsgPort));
return RETURN_FAIL;
}
if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
{
struct Library *xpkbase;
DOSBase = dosbase; /* set global base */
if((xpkbase = OpenLibrary("xpkmaster.library", 4)))
{
struct RDArgs *rda;
struct Args args;
memset(&args, 0, sizeof(struct Args));
XpkBase = xpkbase;
if((rda = ReadArgs(PARAMS, (LONG *) &args, 0)))
{
struct FileInfoBlock *fib;
if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
{
struct AnchorPath *APath;
struct TestData tdat;
ULONG retval;
tdat.password = args.password;
tdat.test = args.test;
tdat.all = args.all;
tdat.save = args.save;
tdat.fib = fib;
if(args.logfile)
tdat.logfh = Open(args.logfile, MODE_READWRITE);
else
tdat.logfh = 0;
if((APath = (struct AnchorPath *) AllocMem(sizeof(struct AnchorPath)+
PATHNAME_SIZE, MEMF_PUBLIC|MEMF_CLEAR)))
{
APath->ap_BreakBits = SIGBREAKF_CTRL_C;
APath->ap_Strlen = PATHNAME_SIZE;
for(retval = MatchFirst(args.filename, APath); !retval; retval = MatchNext(APath))
{
if(APath->ap_Flags & APF_DIDDIR)
APath->ap_Flags &= ~APF_DIDDIR;
else if(APath->ap_Info.fib_DirEntryType > 0)
{
/* if(args.deep)
APath->ap_Flags |= APF_DODIR; */
}
else if((error = DoIt(APath->ap_Buf, &tdat, args.method)))
break;
}
MatchEnd(APath);
FreeMem(APath, sizeof(struct AnchorPath)+PATHNAME_SIZE);
}
if(tdat.logfh)
Close(tdat.logfh);
FreeDosObject(DOS_FIB, fib);
}
FreeArgs(rda);
}
CloseLibrary(xpkbase);
}
if(error && IoErr()) /* print the error */
PrintFault(IoErr(), 0);
CloseLibrary((struct Library *) dosbase);
}
return error;
}
ULONG DoIt(STRPTR name, struct TestData *tdat, STRPTR *method)
{
ULONG error = RETURN_FAIL;
BPTR fh;
if((fh = Open(name, MODE_OLDFILE)))
{
if(ExamineFH(fh, tdat->fib))
{
tdat->sbufsize = tdat->fib->fib_Size;
tdat->ubufsize = tdat->fib->fib_Size + XPK_MARGIN;
tdat->pbufsize = tdat->fib->fib_Size + (tdat->fib->fib_Size>>5) + (XPK_MARGIN<<1);
if((tdat->sbuf = (STRPTR) AllocMem(tdat->sbufsize, MEMF_ANY)))
{
if((tdat->ubuf = (STRPTR) AllocMem(tdat->ubufsize, MEMF_ANY|MEMF_CLEAR)))
{
if((tdat->pbuf = (STRPTR) AllocMem(tdat->pbufsize, MEMF_ANY)))
{
if(Read(fh, tdat->sbuf, tdat->sbufsize) == tdat->sbufsize)
{
struct timerequest timerequest = {0};
if(tdat->test)
{
if((tdat->cbuf = (STRPTR) AllocMem(tdat->sbufsize, MEMF_ANY)))
CopyMem(tdat->sbuf, tdat->cbuf, tdat->sbufsize);
}
else
tdat->cbuf = 0;
if(!OpenDevice("timer.device", UNIT_ECLOCK, (struct IORequest *)
&timerequest, 0))
{
TimerBase = timerequest.tr_node.io_Device;
if((tdat->pinfo = (struct XpkPackerInfo *)
XpkAllocObject(XPKOBJ_PACKERINFO, 0)))
{
if((tdat->minfo = (struct XpkMode *)
XpkAllocObject(XPKOBJ_MODE, 0)))
{
PrintTxt(tdat->logfh, HEADER, name, tdat->sbufsize);
if(method)
{
for(;*method && !CTRL_C; ++method)
{
if(!(*method)[0] || !(*method)[1] ||
!(*method)[2] || !(*method)[3])
PrintErr(tdat->logfh, XPKERR_MISSINGLIB, *method);
else
{
(*method)[0] = toupper((*method)[0]);
(*method)[1] = toupper((*method)[1]);
(*method)[2] = toupper((*method)[2]);
(*method)[3] = toupper((*method)[3]);
if((*method)[4] == '.')
{
(*method)[4] = 0;
DoTest(tdat, *method, strtoul(*method+5, 0,10));
}
else
ScanMethods(tdat, *method);
}
}
}
else
ScanPackers(tdat);
error = 0;
XpkFreeObject(XPKOBJ_MODE, tdat->minfo);
}
XpkFreeObject(XPKOBJ_PACKERINFO, tdat->pinfo);
}
CloseDevice((struct IORequest *) &timerequest);
if(tdat->cbuf)
FreeMem(tdat->cbuf, tdat->sbufsize);
}
}
FreeMem(tdat->pbuf, tdat->pbufsize);
}
FreeMem(tdat->ubuf, tdat->ubufsize);
}
FreeMem(tdat->sbuf, tdat->sbufsize);
}
}
Close(fh);
}
return error;
}
/* These must be defined false, because this is a benchmark tool ! */
static struct TagItem deftags[] = {
{ XPK_Preferences, FALSE},
{ XPK_UseXfdMaster, FALSE},
{ XPK_UseExternals, FALSE},
{ XPK_PassRequest, FALSE},
{ XPK_ChunkReport, FALSE},
{ TAG_DONE, 0},
};
LONG GetPackData(struct BenchData *b, struct TestData *t, STRPTR pwd)
{
struct EClockVal eval1, eval2;
LONG err, d;
ULONG freq;
Forbid();
freq = ReadEClock(&eval1);
err = XpkPackTags(
XPK_InBuf, t->sbuf,
XPK_InLen, t->sbufsize,
XPK_OutBuf, t->pbuf,
XPK_OutBufLen, t->pbufsize,
XPK_GetOutLen, &(b->CSize),
pwd ? XPK_Password : TAG_IGNORE, pwd,
XPK_PackMethod, b->method,
XPK_PackMode, b->mode,
TAG_MORE, deftags);
ReadEClock(&eval2);
Permit();
b->CTime = eval2.ev_lo - eval1.ev_lo;
if(err)
return err;
Forbid();
ReadEClock(&eval1);
err = XpkUnpackTags(
XPK_InBuf, t->pbuf,
XPK_InLen, t->pbufsize,
XPK_OutBuf, t->ubuf,
XPK_OutBufLen, t->ubufsize,
XPK_GetOutLen, &d,
pwd ? XPK_Password : TAG_IGNORE, pwd,
TAG_MORE, deftags);
ReadEClock(&eval2);
Permit();
if(err)
return err;
b->UTime = eval2.ev_lo - eval1.ev_lo;
if(d != t->sbufsize)
{
PrintTxt(t->logfh, SIZEERR, b->method, t->sbufsize, t);
return 1;
}
if(t->test)
{
if(t->cbuf) /* check for destoyed source buffer */
{
for(; d && t->sbuf[d-1] == t->cbuf[d-1]; --d)
;
if(d)
{
CopyMem(t->cbuf, t->sbuf, t->sbufsize); /* restore buffer */
memset(t->ubuf, 0, t->ubufsize);
VPrintTxt(t->logfh, SRCERR, &b->method);
return 1;
}
}
for(d = t->sbufsize; d && t->sbuf[d-1] == t->ubuf[d-1]; --d)
;
memset(t->ubuf, 0, t->ubufsize);
if(d)
{
VPrintTxt(t->logfh, BUFERR, &b->method);
return 1;
}
}
if(t->save)
{
ULONG lock, fh;
if((lock = Lock(t->save, SHARED_LOCK)))
{
lock = CurrentDir(lock);
if(Examine(lock, t->fib) && t->fib->fib_DirEntryType > 0)
{
UBYTE data[10];
sprintf(data, "%.4s.%03ld", b->method, b->mode);
if((fh = Open(data, MODE_NEWFILE)))
{
Write(fh, t->pbuf, b->CSize);
Close(fh);
}
}
UnLock(CurrentDir(lock));
}
}
if((d = 1000 - ((1000 * b->CSize)/t->sbufsize)) < 0)
d = 0;
b->Rate = d/10;
b->Rate10 = d % 10;
b->CTime100 = (100 * (b->CTime % freq)) / freq;
b->UTime100 = (100 * (b->UTime % freq)) / freq;
b->CTime /= freq;
b->UTime /= freq;
if(!b->CTime && !b->CTime100)
b->CTime100 = 1;
if(!b->UTime && !b->UTime100)
b->UTime100 = 1;
b->CSpd = ((100*t->sbufsize) / ((100 * b->CTime) + b->CTime100));
b->USpd = ((100*t->sbufsize) / ((100 * b->UTime) + b->UTime100));
return 0;
}
void DoTest(struct TestData *t, STRPTR method, ULONG mode)
{
struct BenchData b;
struct Library *xbase;
UBYTE libname[] = "compressors/xpk____.library";
LONG err;
CopyMem(method, libname+15, 4);
if(!(xbase = OpenLibrary(libname, 0)))
{
PrintErr(t->logfh, XPKERR_MISSINGLIB, method);
return;
}
b.version = xbase->lib_Version;
b.revision = xbase->lib_Revision;
if(b.revision < 10)
b.pad = " ";
else if(b.revision < 100)
b.pad = " ";
else if(b.revision < 1000)
b.pad = " ";
else
b.pad = "";
CloseLibrary(xbase);
libname[19] = 0;
b.method = libname+15;
if((b.mode = mode) > 100)
b.mode = 100;
if((err = XpkQueryTags(
XPK_PackerQuery, t->pinfo,
XPK_PackMethod, b.method,
TAG_MORE, deftags,
TAG_DONE)))
{
PrintErr(t->logfh, err, b.method);
return;
}
if((t->pinfo->xpi_Flags & XPKIF_NEEDPASSWD) && !t->password)
return;
if((t->pinfo->xpi_Flags & XPKIF_ENCRYPTION) && t->password)
{
b.password = "*";
if((err = GetPackData(&b, t, t->password)))
{
if(err < 0)
PrintErr(t->logfh, err, b.method);
return;
}
else
VPrintTxt(t->logfh, DATATXT, &b);
}
if(!(t->pinfo->xpi_Flags & XPKIF_NEEDPASSWD))
{
b.password = " ";
if((err = GetPackData(&b, t, 0)))
{
if(err < 0)
PrintErr(t->logfh, err, b.method);
return;
}
else
VPrintTxt(t->logfh, DATATXT, &b);
}
}
void ScanPackers(struct TestData *t)
{
LONG err, i;
struct XpkPackerList *pl;
if((pl = (struct XpkPackerList *) XpkAllocObject(XPKOBJ_PACKERLIST, 0)))
{
if((err = XpkQueryTags(
XPK_PackersQuery, pl,
TAG_MORE, deftags,
TAG_DONE)))
{
PrintErr(t->logfh, err, 0);
return;
}
for(i = 0; i < pl->xpl_NumPackers && !CTRL_C; i++)
ScanMethods(t, pl->xpl_Packer[i]);
XpkFreeObject(XPKOBJ_PACKERLIST, pl);
}
}
void PrintTxt(BPTR logfh, STRPTR txt, ...)
{
VPrintTxt(logfh, txt, (APTR) ((ULONG)&txt+sizeof(STRPTR)));
}
void VPrintTxt(BPTR logfh, STRPTR txt, APTR args)
{
VPrintf(txt, args);
if(logfh)
VFPrintf(logfh, txt, args);
}
void PrintErr(BPTR logfh, ULONG err, STRPTR method)
{
UBYTE errbuf[XPKERRMSGSIZE];
XpkFault(err, method, errbuf, XPKERRMSGSIZE);
Printf("%s\n", errbuf);
if(logfh)
FPrintf(logfh, "%s\n", errbuf);
}
void ScanMethods(struct TestData *t, STRPTR method)
{
LONG err;
ULONG mode;
if(t->all)
{
for(mode = 0; mode <= 100 && !CTRL_C; ++mode)
DoTest(t, method, mode);
}
else
{
for(mode = 0; mode < 100 && !CTRL_C; mode = t->minfo->xm_Upto + 1)
{
if((err = XpkQueryTags(
XPK_ModeQuery, t->minfo,
XPK_PackMethod, method,
XPK_PackMode, mode,
TAG_MORE, deftags)))
{
PrintErr(t->logfh, err, method);
return;
}
DoTest(t, method, t->minfo->xm_Upto);
}
}
}